package app.server.project.main.service.service.auth;

import app.server.project.core.exception.SysError;
import app.server.project.core.token.TokenCache;
import app.server.project.core.util.AssertUtil;
import app.server.project.core.util.GlobalValChangeEvent;
import app.server.project.core.websocket.WSMgr;
import app.server.project.main.service.constants.GlobalCfgKey;
import app.server.project.main.service.db.dao.cfg.GlobalCfgDao;
import app.server.project.main.service.db.dao.user.AccountDao;
import app.server.project.main.service.db.dao.user.CMSUserDao;
import app.server.project.main.service.db.dao.user.UserInfoDao;
import app.server.project.main.service.db.entity.user.AccountEntity;
import app.server.project.main.service.db.entity.user.UserInfoEntity;
import app.server.project.main.service.dto.auth.CMSLoginReq;
import app.server.project.main.service.dto.auth.LoginResp;
import app.server.project.main.service.dto.auth.SynDto;
import app.server.project.main.service.dto.auth.TestLoginReq;
import app.server.project.main.service.dto.cms.LockAccountReq;
import app.server.project.main.service.dto.cms.UnBindAccountReq;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
@AllArgsConstructor
public class AuthService {

    public static final String INNER_TOKEN = "955f624a6b8311f0bd6a5b2b1d13485c";

    private AccountDao accountDao;
    private GlobalCfgDao globalCfgDao;
    private UserInfoDao userInfoDao;
    private CMSUserDao cmsUserDao;


    @EventListener(classes = {ApplicationReadyEvent.class, GlobalValChangeEvent.class})
    public void init() {
        TokenCache.setDebug(this.globalCfgDao.getDebug());
    }


    /**
     * 小游戏测试环境登录
     *
     * @param
     */
    public LoginResp appLogin(TestLoginReq req) {
        AccountEntity accountEntity = this.accountDao.getDataByOpenId(req.getOpenId(), ChannelType.TEST);
        AssertUtil.isTrue(!accountEntity.getLock(), SysError.LOCK);
        String token = TokenCache.addToCache(accountEntity.getUserId());
        UserInfoEntity userInfoEntity = this.userInfoDao.getUserInfoById(accountEntity.getUserId());
        var images = List.of("http://gips3.baidu.com/it/u=3886271102,3123389489&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960",
                "https://gips2.baidu.com/it/u=1651586290,17201034&fm=3028&app=3028&f=JPEG&fmt=auto&q=100&size=f600_800",
                "http://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280",
                "http://gips2.baidu.com/it/u=853190258,2588232240&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=720",
                "http://gips0.baidu.com/it/u=3822353666,2757632348&fm=3028&app=3028&f=JPEG&fmt=auto?w=720&h=1280",
                "http://gips3.baidu.com/it/u=764883555,2569275522&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280",
                "http://gips3.baidu.com/it/u=775223787,1959096310&fm=3028&app=3028&f=JPEG&fmt=auto?w=1440&h=2560",
                "http://gips1.baidu.com/it/u=1025173963,4205445645&fm=3028&app=3028&f=JPEG&fmt=auto?w=3200&h=3200",
                "http://gips3.baidu.com/it/u=2489404253,92500118&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280",
                "http://gips0.baidu.com/it/u=1370402140,2009956566&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280"
        );
        int index = RandomUtil.randomInt(0, images.size());
        if (index >= images.size()) index = 0;
        if (StrUtil.isBlank(userInfoEntity.getHeadUrl())) {
            userInfoEntity.setHeadUrl(images.get(index));
        }
        var names = List.of("avra",
                "aquinas",
                "ashia、",
                "ambrosine、",
                "angier、",
                "arin、",
                "ario、",
                "ardara、",
                "alvart、",
                "agnew、",
                "asuncion、",
                "atella");
        int nameIndex = RandomUtil.randomInt(0, names.size());
        if (nameIndex >= names.size()) index = 0;
        if (StrUtil.isBlank(userInfoEntity.getNick())) {
            userInfoEntity.setNick(names.get(index));
        }
        return LoginResp.of(String.valueOf(accountEntity.getUserId()), token);
    }

    public LoginResp cmsLogin(CMSLoginReq req) {
        //后台登录采取默认用户名
        AssertUtil.isTrue(this.cmsUserDao.hasUser(req.getUsername(), req.getPwd()), SysError.CMS_Login_Fail);
        var userId = IdUtil.getSnowflakeNextId();
        String token = TokenCache.addToCache(userId);
        return LoginResp.of(String.valueOf(userId), token);
    }

    /**
     * 封号
     *
     * @param
     */
    public void lockAccount(LockAccountReq req) {
        var nonCache = this.accountDao.getById(req.getUserId());
        var account = this.accountDao.getDataByOpenId(nonCache.getOpenId(), nonCache.getChannel());
        account.setIsLock(req.getLock());
        WSMgr.kick(account.getUserId());
        TokenCache.kick(account.getUserId());
    }

    /**
     * 解绑
     *
     * @param
     */
    public void unBindAccount(UnBindAccountReq req) {
        var nonCache = this.accountDao.getById(req.getUserId());
        var account = this.accountDao.getDataByOpenId(nonCache.getOpenId(), nonCache.getChannel());
        account.setOpenId(String.valueOf(nonCache.getUserId()));
        this.accountDao.delCache(nonCache.getOpenId(), nonCache.getChannel());
        TokenCache.kick(account.getUserId());
    }

    public SynDto getTargetSysToken() {
        String url = this.globalCfgDao.getStr(GlobalCfgKey.Target_Url);
        var respStr = HttpUtil.get(url + "/sys/innerToken/" + INNER_TOKEN);
        return SynDto.of(url, JSONUtil.toBean(respStr, LoginResp.class));
    }

    public LoginResp getInnerSysToken(String innerToken) {
        if (!INNER_TOKEN.equals(innerToken)) {
            return null;
        }
        var userId = IdUtil.getSnowflakeNextId();
        TokenCache.addToCache(userId);
        return LoginResp.of(String.valueOf(userId), TokenCache.addToCache(userId));
    }
}
